#ifndef __DB_H__
#define __DB_H__
#include <mutex>
#include <assert.h>
#include "util.hpp"
class user_table
{
private:
    MYSQL *_mysql;
    std::mutex _mutex;

public:
    user_table(string host,
               string username,
               string password,
               string dbname,
               int port)
    {
        _mysql = mysql_util::mysql_create(host, username, password, dbname, port);
        assert(_mysql != NULL);
    }
    ~user_table()
    {
        mysql_util::mysql_destroy(_mysql);
        _mysql = NULL;
    }
    // 注册
    bool insert(Json::Value &user)
    {
#define INSERT_USER "insert user values(null,'%s',SHA2('%s',256),1000,0,0)"
        Json::Value val;
        char sql_buf[1024];
        sprintf(sql_buf, INSERT_USER, user["username"].asCString(), user["password"].asCString());
        bool n = mysql_util::mysql_exec(_mysql, sql_buf);
        if (n == false)
        {
            mysql_errno(_mysql);
            ELOG("insert user info failed");
            return false;
        }
        return true;
    }
    // 登陆
    bool login(Json::Value &user)
    {
#define LOGIN_USER "select id,score,total_count,win_count from user where username='%s' and password=SHA2('%s',256)"
        char sql_buf[1024];
        sprintf(sql_buf, LOGIN_USER, user["username"].asCString(), user["password"].asCString());
        MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            int n = mysql_util::mysql_exec(_mysql, sql_buf);
            if (n == false)
            {
                DLOG("login fail");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == NULL)
            {
                ELOG("mysql_store_result fail");
                return false;
            }
        }
        int row = mysql_num_rows(res);
        if (row != 1)
        {
            DLOG("username not unique");
            return false;
        }
        MYSQL_ROW line = mysql_fetch_row(res);
        user["id"] = stoi(line[0]);
        user["score"] = stoi(line[1]);
        user["total_count"] = stoi(line[2]);
        user["win_count"] = stoi(line[3]);
        mysql_free_result(res);
        return true;
    }
    // 按用户名查找
    bool select_name(Json::Value &user, const string &name)
    {
#define SELECT_USERNAME "select id,score,total_count,win_count from user where username='%s'"
        char sql_buf[1024];
        sprintf(sql_buf, SELECT_USERNAME, name.c_str());
        MYSQL_RES *res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            int n = mysql_util::mysql_exec(_mysql, sql_buf);
            if (n == false)
            {
                DLOG("select_name fail");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == NULL)
            {
                ELOG("select_name get result fail");
                return false;
            }
        }
        int row = mysql_num_rows(res);
        if (row != 1)
        {
            DLOG("username not unique");
            return false;
        }
        MYSQL_ROW line = mysql_fetch_row(res);
        user["id"] = stoi(line[0]);
        user["username"] = name;
        user["score"] = stoi(line[1]);
        user["total_count"] = stoi(line[2]);
        user["win_count"] = stoi(line[3]);
        mysql_free_result(res);
        return true;
    }
    // 按id查找
    bool select_id(Json::Value &user, const uint64_t &id)
    {
#define SELECT_ID "select username,score,total_count,win_count from user where id=%ld"
        char sql_buf[1024];
        sprintf(sql_buf, SELECT_ID, id);
        MYSQL_RES *res=NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); 
            int n = mysql_util::mysql_exec(_mysql, sql_buf);
            if (n == false)
            {
                DLOG("select_id fail");
                return false;
            }
            res = mysql_store_result(_mysql);
            if (res == NULL)
            {
                ELOG("select_id get result fail");
                return false;
            }
        }
        int row = mysql_num_rows(res);
        if (row != 1)
        {
            std::cout<<row<<std::endl;
            DLOG("username not unique");
            return false;
        }
        MYSQL_ROW line = mysql_fetch_row(res);
        user["id"] = id;
        user["username"] = line[0];
        user["score"] = stoi(line[1]);
        user["total_count"] = stoi(line[2]);
        user["win_count"] = stoi(line[3]);
        mysql_free_result(res);
        return true;
    }
    // 更新数据 赢
    // 天梯分数加30，场数加1，赢数加1
    bool win(const int &id)
    {
#define WIN_USER "update user set score=score+30,total_count=total_count+1,win_count=win_count+1 where id=%d"
        char sql_buf[1024];
        sprintf(sql_buf, WIN_USER, id);
        bool n = mysql_util::mysql_exec(_mysql, sql_buf);
        if (n == false)
        {
            ELOG("win update fail");
            return false;
        }
        return true;
    }
    // 更新数据 输
    bool lose(const int &id)
    {
#define LOSE_USER "update user set score=score-30,total_count=total_count+1 where id=%d"
        char sql_buf[1024];
        sprintf(sql_buf, LOSE_USER, id);
        bool n = mysql_util::mysql_exec(_mysql, sql_buf);
        if (n == false)
        {
            ELOG("lose update fail");
            return false;
        }
        return true;
    }
};
#endif